using System;
using System.IO;
using System.Diagnostics;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Collections.Specialized;

namespace My.IdlConverter.Core.Parsers
{
    using Filters;
    using Util;

    public class ClassParser : ParserBase
    {
        public static readonly string VTL_INTERFACE_ENTRY_REGEX = @"VTL_.*_INTERFACE_ENTRY\(.*\)";
        public static readonly string ABSTRACT_CLASS_REGEX = @"VTL_BEGIN_CLASS_DECLARE\(VCLSID_0\)";
        public static readonly string CV_DOM_REGEX = @"\(Cv_DOM.*?\)";
        public static readonly string IV_DOM_REGEX = @"\(Iv_DOM.*?\)";
        public static readonly string CLASS_METHOD_REGEX = @"virtual.*";
        public static readonly string PUBLIC_METHODS_SEG_REGEX = @";.*public:.*[const,)];";

        public ClassParser()
            :base()
        {
        }

        ~ClassParser() { }

        public override object Parse(string target)
        {
            try
            {
                string classString = null;
                if (!Util.IOHelper.ReadToEnd(target, out classString))
                {
                    Debug.Assert(false);
                    return null;
                }
                if (!Recognizer.RecognizeClassFile(target, classString))
                {
                    Trace.WriteLine(String.Format("The class file ({0} is not Cv_DOM class file) ", target));
                    return null;
                }
                classString = ClassStore.AddInherit(target);
                string className = Recognizer.GetDOMClassName(target);

                Class theClass = ClassStore.GetClass(className);
                if (theClass != null)
                {
                    FillMethods(classString, ref theClass);
                    FillClassAttribute(theClass, classString);
                }
                return theClass;
            }
            catch (Exception e)
            {
                //Debug.Assert(false);
                Trace.Write(e.Message);
                return null;
            }
        }

        private void FillClassAttribute(Class theClass, string classString)
        {
            if (Regex.IsMatch(classString, ABSTRACT_CLASS_REGEX)
                || Regex.IsMatch(classString, InterfaceParser.InterfaceMethodRegex)
                || AbstractClassNameCollection.Contains(theClass.Name) )
            {
                theClass.Abstract = true;
            }
            else
            {
                theClass.Abstract = false;
            }
        }

        private void FillMethods(string classString,ref Class theClass)
        {
            IParser methodParser = new MethodParser();

            MatchCollection matchCol = Regex.Matches(classString, CLASS_METHOD_REGEX);
            string methodEntry = null;

            foreach (Match nextMatch in matchCol)
            {
                methodEntry = nextMatch.Value;
                if (!Recognizer.RecognizeMethod(methodEntry))
                    continue;
                if (MethodModifier.IsAspiredMethod(methodEntry))
                {
                    Method newMethod = methodParser.Parse(methodEntry) as Method;

                    if (newMethod != null)
                    {
                        newMethod.Parent = theClass;
                        theClass.Methods.Add(newMethod);

                        if (OverloadCollision != null)
                            OverloadCollision.CacheMethods.Add(newMethod);
                    }
                    else
                        Debug.Assert(false);
                }
            }
        }
    }
}
